package main

import (
	"container/list"
	"fmt"
)

// 来源：2022 字节青训营 进阶班算法第一题
// 题干：
// 电影院可以为用户自动预定所有连在一起的位置，
// 给一个 n*m 的图，图中每个点表示一个座位/障碍,
// 如果节点是 0 的话说明有位置
// 是 1 的话说明是障碍或者没有位置
// 请算出所有连在一起的位置

// 案例输入：
// 3
// 3
// 1 0 0
// 1 1 0
// 0 0 1
// 案例输出：
// 3

// 解题思路：
// 维护一个 plaint 集合，包含所有空余的位置的坐标
// 遍历 plaint 集合的一个元素，利用 BFS 查出所有相连的空位
// 并把空位从 plaint 集合内删除 (剪枝)
// 遍历完 plaint，输出 max

const Max = 100 // 最大高宽

var seats [Max][Max]int
var plaint = make(map[[2]int]struct{})
var x, y int

func main() {
	fmt.Scanf("%d\n%d", &x, &y)
	for i := 0; i < x; i++ {
		for j := 0; j < y; j++ {
			fmt.Scanf("%d", &seats[i][j])
			seats[i][j]++
			if seats[i][j] == 1 {
				plaint[[2]int{i, j}] = struct{}{}
			}
		}
	}
	fmt.Println(solve())
}

func solve() int {
	var max = 0
	for p := range plaint {
		var l = list.New()
		var looked = make(map[[2]int]struct{})
		l.PushBack(p)
		var sum = 1
		for l.Len() != 0 {
			e := l.Front()
			l.Remove(e)
			pos := e.Value.([2]int)
			looked[pos] = struct{}{}
			delete(plaint, pos)

			near := getNear(pos)
			for _, n := range near {
				if _, ok := looked[n]; ok {
					continue
				}
				if seats[n[0]][n[1]] == 1 {
					looked[n] = struct{}{}
					l.PushBack(n)
					sum++
				}
			}
		}
		if sum > max {
			max = sum
		}
	}
	return max
}

func getNear(pos [2]int) [4][2]int {
	px := pos[0]
	py := pos[1]
	lx := px - 1
	rx := px + 1
	uy := py - 1
	dy := py + 1
	if lx < 0 {
		lx = 0
	}
	if rx > x-1 {
		rx = x - 1
	}
	if uy < 0 {
		uy = 0
	}
	if dy > y-1 {
		dy = y - 1
	}
	return [4][2]int{{lx, py}, {rx, py}, {px, uy}, {px, dy}} // left, right, up, down
}
